package org.chispa.api.visitors;

import java.security.NoSuchAlgorithmException;

import org.chispa.api.query.ParamWrapper;
import org.chispa.api.util.BadSyntaxException;
import org.chispa.api.util.BinningNumber;
import org.chispa.api.util.NoSuitableVisitorException;

import com.google.common.annotations.VisibleForTesting;

@VisibleForTesting
public class SimpleQueryVisitor implements QueryVisitor<String,Long> {

	ParamVisitor<String,String,String> stringVisit;
	ParamVisitor<String,String,String> stringExprVisit;
	ParamVisitor<BinningNumber,Long,String> floatVisit;
	ParamVisitor<BinningNumber,Long,String> intVisit;
	ParamVisitor<String, String, String> floatExprVisit;
	ParamVisitor<String, String, String> intExprVisit;

	public SimpleQueryVisitor(ParamVisitorFactory<String,String,String> stringFact,
			ParamVisitorFactory<BinningNumber,Long,String> floatFact,
			ParamVisitorFactory<BinningNumber,Long,String> intFact){

		try {
			if(stringFact!=null)
			{
				stringVisit=stringFact.createVisitor();
				stringExprVisit=stringFact.createVisitorForExpr();
			}
			if(floatFact!=null)
			{
				floatVisit=floatFact.createVisitor();
				floatExprVisit=floatFact.createVisitorForExpr();
			}
			if(intFact!=null)
			{
				intVisit=intFact.createVisitor();
				intExprVisit=intFact.createVisitorForExpr();
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

	}

	@Override
	public String visitStringHash(ParamWrapper<String,String,String> wrap) throws NoSuitableVisitorException, BadSyntaxException {
		if(stringVisit==null && stringExprVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptHash(stringVisit==null?stringExprVisit:stringVisit);
	}

	@Override
	public String visitString(ParamWrapper<String, String, String> wrap)
			throws NoSuitableVisitorException {
		if(stringVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptEnc(stringVisit);
	}

	@Override
	public String visitFloat(ParamWrapper<BinningNumber, Long, String> wrap)
			throws NoSuitableVisitorException {
		if(floatVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptEnc(floatVisit);
	}

	@Override
	public String visitInt(ParamWrapper<BinningNumber, Long, String> wrap)
			throws NoSuitableVisitorException {
		if(intVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptEnc(intVisit);
	}

	@Override
	public Long visitFloatHash(ParamWrapper<BinningNumber, Long, String> wrap) throws NoSuitableVisitorException, BadSyntaxException {
		if(floatVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptHash(floatVisit);
	}

	@Override
	public Long visitIntHash(ParamWrapper<BinningNumber, Long, String> wrap) throws NoSuitableVisitorException, BadSyntaxException {
		if(intVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptHash(intVisit);
	}

	@Override
	public String visitFloatHashExpr(
			ParamWrapper<String, String, String> wrap)
			throws NoSuitableVisitorException, BadSyntaxException {
		if(floatExprVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptHash(floatExprVisit);
	}

	@Override
	public String visitIntHashExpr(
			ParamWrapper<String, String, String> wrap)
			throws NoSuitableVisitorException, BadSyntaxException {
		if(intExprVisit==null)
			throw new NoSuitableVisitorException();
		return wrap.acceptHash(intExprVisit);
	}

	@Override
	public String visitDecryptNum(ParamWrapper<String, String, String> wrap) throws NoSuitableVisitorException {
		if(floatVisit==null)
			throw new NoSuitableVisitorException();
		return floatVisit.visitDecrypt(wrap.getWrappedParam());
	}

	

	

	
}
